import datetime
import Core.WindFunctions as Wind
import Core.Gadget as Gadget


# ---更新公募基金列表---
def Download_MutualFund_List(database, force_to_update=False):
    #
    datetime1 = datetime.datetime.now()

    # ---Load Database---
    # instrumentsInDatabase
    dic_listed_fund_inDatabase = {} # 全部基金
    dic_total_fund_inDatabase = {} # 在市基金
    instruments = database.Find("financial_data", "instrument_mutualfund")
    for instrument in instruments:
        symbol = instrument["symbol"]
        dic_total_fund_inDatabase[symbol] = instrument
        #
        if instrument["datetime2"] == datetime.datetime(2100, 1, 1):
            dic_listed_fund_inDatabase[symbol] = instrument
    #
    dic_delist_fund = {}
    data2, dt2 = Wind.WSet_Instruments(datetime1, sectorName="已摘牌基金")
    for i in range(len(data2)):
        d = data2[i]
        symbol = d["Symbol"]
        name = d["Name"]
        dic_delist_fund[symbol] = {"Name": name}
    #
    dic_total_fund = {}
    data, dt = Wind.WSet_Instruments(datetime1, sectorName="全部基金(含未成立、已到期)")
    for i in range(len(data)):
        d = data[i]
        symbol = d["Symbol"]
        name = d["Name"]
        dic_total_fund[symbol] = {"Name": name}

    # ---新建基金条目---
    # ---太多崩溃，分批提取---
    step = 1000
    for i in range(0, len(data), step):
        print("Download_MutualFund_List", i, "to", i + step)
        patialData = data[i:i + step]
        names = []
        symbols = []
        #
        for j in range(len(patialData)):
            d = patialData[j]
            symbol = d["Symbol"]
            name = d["Name"]
            #
            if force_to_update == True: # ---Force To Update 强制更新---
                symbols.append(symbol)
                names.append(name)
            #
            else:# ---智能更新---
                existed = dic_total_fund_inDatabase.get(symbol)
                if existed == None:
                    # 不存在，新建
                    #print("Not Existed " + symbol)
                    symbols.append(symbol)
                    names.append(name)
                else:
                    pass

        # ---Create New fund---
        if len(symbols) > 0:
            print("New Mutual Fund #", len(symbols))
            Download_MutualFund_Info(database, datetime1, symbols, names)

    # ---更新状态---
    to_update_state = []  # 有些需要更新日期 （起始日，到期日）
    for symbol, value in dic_listed_fund_inDatabase.items():
        # --- 是否已经下市---
        existed = dic_delist_fund.get(symbol)
        if existed:
            to_update_state.append(symbol)
        else:
            pass
        # ---数据库中是未上市状态， Try是否已经上市---
        if value["datetime1"] <= datetime.datetime(1900, 1, 1):
            to_update_state.append(symbol)

    # ---Update Datetime1 DateTime2---
    if len(to_update_state) > 0:
        # print("Update Mutual Fund #", len(symbolsToUpdateDateTime))
        Update_MutualFund_DateTimes(database, to_update_state, dic_total_fund_inDatabase)


# ---更新公募基金全部细节---
def Download_MutualFund_Info(database, tradeDate, symbols, names):
    # ---基本要素---
    fields = ["fund_fullname"]
    fields.append("fund_investobject") # 投资目标
    fields.append("fund_investscope") # 投资范围
    # ---重要日期---
    fields.append("fund_setupdate")  # 基金成立日
    fields.append("fund_maturitydate")  # 基金到期日
    fields.append("ipo_date")  # 上市日期和成立日不一致问题
    # ---中介机构---
    fields.append("fund_mgrcomp")  # 基金管理人
    fields.append("fund_custodianbank")  # 基金托管人
    # ---基金分类---
    fields.append("fund_type")  # 基金类型
    fields.append("fund_firstinvesttype")  # 投资类型(一级分类)
    fields.append("fund_investtype")  # 投资类型(二级分类)
    fields.append("fund_structuredfundornot")  # 是否分级基金
    #
    fields.append("fund_trackindexcode")  # 跟踪指数代码
    fields.append("fund_etfwindcode")  # 关联ETFWind代码
    # ---基金经理相关---
    fields.append("fund_fundmanager")  # 基金经理（现任）
    fields.append("fund_manager_managerworkingyears")  # 基金经理从业时间 order=1
    fields.append("fund_manager_geometricannualizedyield")  # 几何年化收益 order=1
    #
    params = {}
    params["order"] = 1  # 基金经理顺位，但是wind数据中顺序经常是错的
    params["returnType"] = 1  # 非对数收益率
    #
    data = Wind.WSS(symbols, fields, params)

    # ---Save to DataBase---
    documents = []
    for iSymbols in range(len(symbols)):
        symbol = symbols[iSymbols]
        d = data[iSymbols]
        if symbol == "001696.OF":
            kkwood = 0

        dataObject = {}
        dataObject["Symbol"] = symbol
        dataObject["date"] = dataObject["datetime"] = tradeDate
        #
        # dataObject["DateTime"] = Gadget.ToDateTimeString(tradeDate)
        # dataObject["StdDateTime"] = Gadget.ToUTCDateTime(tradeDate)
        dataObject["Instrument_Type"] = "MutualFund"
        dataObject["Description"] = names[iSymbols]
        dataObject["Currency"] = "CNY"
        dataObject["Key2"] = symbol
        #
        datetime1 = d["fund_setupdate"]
        datetime1 = Gadget.FilterWindDateTimeDirty(datetime1)
        # if datetime1 < datetime(1900,1,1):
        #     dataObject["SetupDate"] = datetime1
        # else:
        #     dataObject["SetupDate"] = Gadget.ToUTCDateTime(datetime1)
        dataObject["Setup_Date"] = datetime1
        dataObject["DateTime1"] = dataObject["Setup_Date"]

        #
        deListDate = d["fund_maturitydate"]
        if deListDate > datetime.datetime(1900,1,1):
            deListDate = Gadget.FilterWindDateTimeDirty(deListDate)
            # dataObject["MaturityDate"] = Gadget.ToUTCDateTime(deListDate)
            dataObject["Maturity_Date"] = deListDate
            dataObject["DateTime2"] = dataObject["Maturity_Date"]
        else:
            maxDateTime = datetime.datetime(2100, 1, 1)
            # maxDateTime = Gadget.ToUTCDateTime(maxDateTime)
            dataObject["Maturity_Date"] = maxDateTime
            dataObject["DateTime2"] = maxDateTime

        #
        dataObject["FullName"] = d["fund_fullname"]
        dataObject["Invest_Object"] = d["fund_investobject"]
        dataObject["Invest_Scope"] = d["fund_investscope"]
        dataObject["Manage_Company"] = d["fund_mgrcomp"]
        dataObject["Custodian_Bank"] = d["fund_custodianbank"]
        dataObject["Fund_Type"] = d["fund_type"]
        dataObject["Invest_Type1"] = d["fund_firstinvesttype"]
        dataObject["Invest_Type2"] = d["fund_investtype"]
        dataObject["Structured_Fund"] = d["fund_structuredfundornot"]
        dataObject["Tracking"] = d["fund_trackindexcode"]
        dataObject["Linked_ETF"] = d["fund_etfwindcode"]
        #
        dataObject["Manager_Name"] = d["fund_fundmanager"]
        dataObject["Manager_Working_Years"] = d["fund_manager_managerworkingyears"]
        dataObject["Manager_Average_Annualized_Return"] = d["fund_manager_geometricannualizedyield"]
        #
        print("Create New MutualFund" , symbol)
        documents.append(dataObject)
        # database.Upsert("Instruments", "MutualFund", {"Symbol": symbol}, dataObject)
        kkwood = 1
    #
    database.Upsert_Many("financial_data", "instrument_mutualfund", {}, documents)


# ---更新募基金全成立、清算信息---
def Update_MutualFund_DateTimes(database, symbols, instrumentsInDatabase):
    #
    fields = []
    fields.append("fund_setupdate")
    fields.append("fund_maturitydate")
    #
    data = Wind.WSS(symbols, fields)
    #
    count = 0
    for iSymbol in range(len(symbols)):
        symbol = symbols[iSymbol]
        #
        datetime1 = data[iSymbol]["fund_setupdate"]
        datetime2 = data[iSymbol]["fund_maturitydate"]
        dataObject = {}
        dataObject["Symbol"] = symbol
        update = False

        element = instrumentsInDatabase.get(symbol)
        if element == None:
            print("Symbol Not Existed " + symbol)
            continue

        datetime1InDatabase = Gadget.DeleteTimeZone(element["datetime1"])
        # Find valid Setup Date
        if datetime1 > datetime.datetime(1900, 1, 1):
            print("Update DateTime1 " + symbol + " @ " + str(datetime1))
            dataObject["setup_date"] = datetime1
            dataObject["datetime1"] = dataObject["setup_date"]
            update = True

        # Find a valid maturity date
        if datetime2 > datetime.datetime(1900, 1, 1) and datetime2 < datetime.datetime(2100, 1, 1):
            print("Update DateTime2 " + symbol + " @ " + str(datetime2))
            dataObject["maturity_date"] = datetime2
            dataObject["datetime2"] = dataObject["maturity_date"]
            update = True

        if update:
            print("Update Mutual Fund Datetimes", symbol)
            database.Update("financial_data", "instrument_mutualfund", target={"Symbol": symbol}, document=dataObject)


def Download_MutualFund_IPO_Date(database):
    #
    #instruments = database.findWithFilter("Instruments", "MutualFund")
    symbols = []
    #for instrument in instruments:
    #    symbols.append(instrument["Symbol"])

    symbols.append("184720.OF")
    symbols.append("500028.OF")
    symbols.append("184719.OF")
    symbols.append("500013.OF")
    symbols.append("500017.OF")
    symbols.append("184709.OF")
    symbols.append("184711.OF")
    symbols.append("184738.OF")
    symbols.append("500019.OF")
    symbols.append("500039.OF")
    symbols.append("500035.OF")
    symbols.append("184708.OF")
    symbols.append("500010.OF")
    symbols.append("500021.OF")
    symbols.append("500029.OF")
    symbols.append("184702.OF")
    symbols.append("184710.OF")
    symbols.append("500016.OF")
    symbols.append("184695.OF")
    symbols.append("184718.OF")
    symbols.append("184696.OF")
    symbols.append("500025.OF")

    step = 1000
    for i in range(0, len(symbols), step):
        patialData = symbols[i:i + step]
        fields = "ipo_date"
        data = Wind.WSS(patialData, fields)
        for j in range(len(data)):
            symbol = patialData[j]
            if data[j]["ipo_date"] > datetime.datetime(1900,1,1):
                print(symbol + " " + str(data[j]["ipo_date"]))
                target = {}
                target["Symbol"] = symbol
                dataObject = {"DateTime1": Gadget.ToUTCDateTime(data[j]["ipo_date"])}
                database.update("Instruments", "MutualFund", target, dataObject)
                kkwood = 1
        kkwood = 0

    kkwood = 0


# ---Mutual Fund---
def FixMutualFundDateTime(database):
    #
    instruments = database.Find("Instruments", "MutualFund")
    for instrument in instruments:
        symbol = instrument["Symbol"]
        dataObject = {}
        if "MaturityDate" not in instrument:
            print(symbol)
            maxDateTime = datetime.datetime(2100, 1, 1)
            maxDateTime = Gadget.ToUTCDateTime(maxDateTime)
            dataObject["MaturityDate"] = maxDateTime
            dataObject["DateTime2"] = maxDateTime
            database.upsert("Instruments", "MutualFund", {"Key":symbol}, dataObject)
            k = 1

